Mapping Energy Access and Solar Potential
UNDP Nigeria Data Hub

Mapping Energy Access in Nigeria
UNDP Nigeria
Data Hub

Nigeria at Night
VIIRS Daily Composite Averages (2022–2024)


Access to reliable electricity remains a significant challenge across sub-Saharan Africa. Nigeria, Africa’s most populous and the continent’s second largest economy, continues to grapple with widespread energy poverty, impacting households, productive sectors, and essential public service delivery.

To support more targeted and evidence-based energy planning, this analysis leverages satellite-derived nighttime lights data as a spatial proxy for electricity access. Specifically, daily observations from the Visible Infrared Imaging Radiometer Suite (VIIRS) sensor, using the Gap-Filled DNB BRDF-Corrected Nighttime Lights product at 500-meter resolution, was used to analyze lighting patterns across Nigeria from 2022 to 2024. Daily VIIRS nightlights data from 2022 to 2024 (Gap_Filled_DNB_BRDF_Corrected_NTL band) were composited into annual mean rasters covering the period 2020-2024.

By analyzing the intensity and spatial distribution of nighlights across Nigeria, we estimate the electrification footprint and highlight persistently dark or under-served areas that may lack grid connectivity. While the methodology is optimised for in-country analysis, the results are not intended for cross-country comparisons as normalisation was performed using Nigeria specific distributions.

This analysis provides a foundation for more granular energy access assessments and helps identify high-priority locations for solar and decentralized energy interventions, particularly in rural and peri-urban areas with limited infrastructure.

Energy Access Clusters
Gaussian Mixture Model (GMM) Classification


To estimate spatial patterns of electricity access across Nigeria, satellite-derived nighttime light intensity data (VIIRS, 500m resolution, 2022–2024) were normalized, transformed and analysed using unsupervised clustering techniques to improve comparability across geographic areas. Several transformation techniques were tested, including logarithmic scaling, square root, Box-Cox, and histogram equalization, to optomise the distribution of light values. Ultimately, the normalized mean raster was selected for clustering, as it exhibited a near-symmetric, bell-shaped distribution ideal for unsupervised classification.

Two clustering algorithms were evaluated: K-Means and Gaussian Mixture Modeling (GMM). Both methods produced broadly consistent results, with over 80% spatial overlap in cluster assignments. However, GMM was selected for the final classification due to its probabilistic structure, which better captures gradual transitions and ambiguity, particularly in peri-urban or semi-electrified areas where light intensity changes are not abrupt.

Unlike K-Means, which imposes hard boundaries between clusters, GMM models overlapping distributions and is therefore more flexible in representing mixed or transitional access zones. Silhouette analysis supported a four-cluster solution, offering the best trade-off between statistical cohesion and interpretability.

The final classification assigned each 500m pixel to one of four electricity access tiers based on the distribution of normalized light intensity values:

This GMM-based typology provides a spatially continuous, high-resolution map of electricity access across Nigeria. It enables a more targeted planning and identification of under-served populations, including hidden deprivation within partially electrified regions.

Energy Access Typologies
Cluster-Specific Spatial Patterns


The four maps depict distinct typologies of energy access derived from the GMM classification. Each typology corresponds to a different access tier and reveals the spatial distribution of energy inequality across Nigeria:

Together, the maps provide a nuanced spatial typology of electricity access, enabling visual identification of priority regions for energy investment and solar deployment.

Population Density and Energy Access Identifying Underserved High-Density Areas


To pinpoint where energy deprivation intersects most critically with human settlement, the analysis overlays the GMM classified electricity access typologies with smoothed population density surfaces derived from the Global Human Settlement Layer (GHS-POP). GHS-POP provides gridded population estimates at ~1km resolution, enabling disaggregated spatial analysis across the four electricity access tiers.

To emphasize regional clusters over isolated outliers, a 51×51 pixel kernel smoothing filter was applied to the population rasters within each access category. This revealed not only where people live, but how densely they are concentrated. Pixels with fewer than 100 people/km² were rendered in gray to de-emphasize sparsely populated zones and instead highlight areas with concentrated human presence.

The resulting maps reveal a stark spatial mismatch in many parts of the country: large, densely populated areas, particularly across northern Nigeria and the Middle Belt, fall within zones classified as having very low or no electricity access. These hotspots represent high-priority intervention zones, where infrastructure deficits directly affect large populations.

Conversely, high-access zones align closely with major urban centers particularly in the southern regions of the country, confirming an urban–infrastructure nexus. Medium access areas form a transitional ring around secondary cities and expanding peri-urban zones, while low access areas show scattered yet significant population densities, often in emerging rural towns or underserved settlements.

Some areas within the “very low access” class appear sparsely populated. This is expected in locations such as national parks, wetlands, or terrain unsuitable for habitation, and may also reflect limitations of satellite-based population detection in dispersed rural areas.

By intersecting electricity access classifications with population density, the analysis shifts from infrastructure mapping to human-centered energy diagnostics, providing a sharper basis for prioritizing interventions based on real-world needs.

State-Level Energy Poverty Estimates
Disaggregating Electricity Access by Population and Geography


This section disaggregates electricity access and energy poverty at the state level, combining GMM-classified nightlight-based access typologies with high-resolution population estimates (GHS-POP 2025) to reveal the scale and spatial distribution of under-served populations across Nigeria. While these are population estimates derived from the GHS-POP model, they still offer valuable spatial insight into settlement patterns and the population distribution of energy poverty.

By overlaying each electricity access class, ranging from No/Very Low to High Access, with gridded population surfaces (~1 km resolution), the analysis generates population-adjusted estimates of energy deprivation. This allows not only quantification of affected populations, but also identification of where energy poverty is most concentrated within each state.

To visualize these dynamics, the card presents three linked views:

Together, these views highlight both relative and absolute disparities. They help identify priority states with both high energy poverty rates and large affected populations For instance, two states may have similar percentages of energy-poor populations, but vastly different population sizes—amplifying the need for population-adjusted targeting in energy access planning.

LGA-Level Energy Poverty Estimates
Hotspots and Localised Deficit Scores


The analysis was extended to cater for a more operational and locally actionable scale, energy access estimates were disaggregated to Nigeria’s 774 LGAs. This LGA-level view allows for finer geographic targeting and supports more tailored interventions, especially in high-burden and under-served communities that may be overlooked in state-level averages.

To synthesize two dimensions of energy poverty intensity (% of population without access) and scale (absolute number affected), a composite Energy Access Deficit score was developed. This score combines normalized values of energy poverty percentage and estimated energy-poor population to flag LGAs where unmet energy needs are both widespread and numerically large.

The interactive map displays LGA-level Energy Access Deficit scores across Nigeria, while the accompanying searchable table provides access statistics and scores by LGA and state.

Note: Population estimates are derived from modeled data (GHS-POP 2025) and should be interpreted as indicative. While not based on recent census data, they offer valuable insight into spatial patterns of deprivation and remain useful for planning and prioritization.

Energy Access in Health Facilities Mapping Energy Deprivation Across Public Hospitals


[graphics to be rendered] This section overlays public hospital locations with GMM-classified electricity access typologies to highlight the availability of energy infrastructure at health facilities across Nigeria. By categorizing each hospital into four access levels—No/Very Low, Low, Medium, and High—the analysis identifies critical service points operating under severe energy constraints.

Public hospitals in No/Very Low Access zones often serve as primary health centers for underserved communities. Identifying and mapping these facilities provides a clear entry point for infrastructure investment planning—especially solarization or mini-grid solutions.

To support prioritization, the dashboard presents:

Note: Only public hospitals were included (federal, state, and local government facilities).

Critical Healthcare Infrastructure Findings:

Priority States for Healthcare Energy Interventions: The northern states of Borno, Katsina, Bauchi, and Jigawa emerge as top priorities, combining high numbers of energy-poor healthcare facilities with large populations lacking electricity access.

This analysis underscores the critical intersection between energy poverty and healthcare delivery, where reliable electricity is essential for medical equipment, vaccine cold chains, lighting for night deliveries, and overall healthcare quality.

Energy Poverty and Solar Potential
Strategic Opportunities for Renewable Energy


To do

---
title: "UNDP Nigeria Knowledge Hub | Mapping Energy Access and Solar Potential"
output: 
  flexdashboard::flex_dashboard:
    storyboard: true
    social: menu
    source: embed
    css: styles.css
    scroll: yes
 
---

```{r setup, include=FALSE, results = 'asis'}

pacman::p_load(flexdashboard,leaflet,leaflet.extras,sf,RColorBrewer,terra,raster, viridis,tmap, shiny,htmltools, plotly, tidyr, dplyr, DT, crosstalk)
terraOptions(progress = 0)  

```


### **Mapping Energy Access and Solar Potential** <br> UNDP Nigeria Data Hub 

```{r, cover-page, echo = FALSE, warnings = FALSE}

  cover_card <- tags$div(
    style = "position: relative; width: 100%; height: 100vh; margin: 0; padding: 0; overflow: hidden; border-radius: 0;",
  
    # Temp image- ask Comms team for Nieria image
    tags$img(
      src = "/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/CO REQUESTS/2024/Energy/Access_Solar_Analysis/graphics_presentation/CoverPage_Test.jpg",
      style = "width: 100%; height: 100%; object-fit: cover; filter: brightness(0.6);"
    ),
  
    # Top text
    tags$div(
      "Mapping Energy Access in Nigeria",
      style = "position: absolute; top: 48%; left: 50%;
               transform: translate(-50%, -50%);
               font-size: 42px; font-weight: bold;
               color: white; text-align: center;
               font-family: 'Helvetica Neue', sans-serif;"
    ),
  
    # Subtitle
  tags$div(
    style = "position: absolute; top: 58%; left: 50%; transform: translate(-50%, -50%);
             font-size: 22px; font-weight: normal;
             color: white; text-align: center;",
    "UNDP Nigeria", tags$br(), "Data Hub"
  ))
  
  cover_card

```

### **Nigeria at Night**<br>VIIRS Daily Composite Averages (2022–2024)

```{r nightlights-map, fig.width=12, fig.height=8, echo=FALSE, message=FALSE, fig.bg = "black",  warning=FALSE}

  tiff_path <- "/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/CO REQUESTS/2024/Energy/Access_Solar_Analysis/graphics_presentation/mean_raster_norm.tif"
  
  raster_data <- rast(tiff_path)
  
  # Transform for visual enhancement
  mean_raster_vis <- raster_data^3
  
  r_proj <- project(mean_raster_vis, "EPSG:3857")
  
  r_downsampled <- aggregate(r_proj, fact = 4, fun = mean)


  nasa_palette <- colorRampPalette(c(
    "#000000",  
    "#0C0C2C",  
    "#1F1F4D", 
    "#4A3005", 
    "#FFB100",  
    "#FFF5CC"   
  ))
  
  colors <- nasa_palette(100)
  pal <- colorNumeric(palette = colors, domain = values(r_proj), na.color = "transparent")

  #par(bg = "black", mar = c(0, 0, 0, 0))

  #plot(mean_raster_vis,
   #    col = colors,
    #   axes = FALSE,
     #  box = FALSE,
      # legend = FALSE,
       #main = "",
       #bg = "black")
  
  
  leaflet() %>%
    addProviderTiles(providers$CartoDB.DarkMatter) %>%  
    addRasterImage(r_downsampled, colors = pal, opacity = 0.9) %>%
    addLegend(pal = pal, values = values(r_proj), title = "Nightlight <br> Intensity") %>%
    setView(lng = 8.6753, lat = 9.0820, zoom = 7) %>% 
    addControl(
    html = HTML("<div style='font-size:10px; color:gray; padding:4px;'>*Note: Night light data shown for Nigeria only. </div>"),
    position = "bottomleft"
  )
  
```

***

Access to reliable electricity remains a significant challenge across sub-Saharan Africa. Nigeria, Africa's most populous and the continent’s second largest economy, continues to grapple with widespread energy poverty, impacting households, productive sectors, and essential public service delivery.

To support more targeted and evidence-based energy planning, this analysis leverages satellite-derived nighttime lights data as a spatial proxy for electricity access. Specifically, daily observations from the Visible Infrared Imaging Radiometer Suite (VIIRS) sensor, using the Gap-Filled DNB BRDF-Corrected Nighttime Lights product at 500-meter resolution, was used to analyze lighting patterns across Nigeria from 2022 to 2024. Daily VIIRS nightlights data from 2022 to 2024 (Gap_Filled_DNB_BRDF_Corrected_NTL band) were composited into annual mean rasters covering the period 2020-2024.

By analyzing the intensity and spatial distribution of nighlights across Nigeria, we estimate the electrification footprint and highlight persistently dark or under-served areas that may lack grid connectivity. While the methodology is optimised for in-country analysis, the results are not intended for cross-country comparisons as normalisation was performed using Nigeria specific distributions. 

This analysis provides a foundation for more granular energy access assessments and helps identify high-priority locations for solar and decentralized energy interventions, particularly in rural and peri-urban areas with limited infrastructure.


### **Energy Access Clusters** <br> Gaussian Mixture Model (GMM) Classification

```{r gmm, warning = FALSE, message = FALSE, echo = FALSE}

  # cluster_colors <- c( "#253494",  # Dark blue - Low/No Access, "#2c7fb8",  # Teal Blue - Moderate Access,  "#fd8d3c",  # Orange - High Access, "#ffffcc"   # Light Yellow - Highly Accessed)
  # Load the raster
    tiff_path <- "/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/CO REQUESTS/2024/Energy/Access_Solar_Analysis/graphics_presentation/access_level_raster.tif"
  raster_data <- rast(tiff_path)
  r_proj <- project(raster_data, "EPSG:4326")
  
  # Downsample 
  r_downsampled <- aggregate(r_proj, fact = 2, fun = modal)
  raster_r <- raster(r_downsampled)
  
  # Colors
  cluster_colors <- c("#440154FF", "#31688EFF", "#35B779FF", "#FDE725FF")
  cluster_labels <- c("Very Low/No Access", "Low Access", "Medium Access", "High Access")
  pal <- colorFactor(palette = cluster_colors, domain = 1:4, na.color = "transparent")

  
  # Map
  leaflet() %>%
    addProviderTiles("CartoDB.DarkMatter") %>%
    # Add masked raster
    addRasterImage(raster_r, colors = pal, opacity = 0.8, project = FALSE) %>%
    # Legend
    addLegend(position = "topright",
              colors = cluster_colors,
              labels = cluster_labels,
              title = "Electricity Access Clusters",
              opacity = 1) %>%
    setView(lng = 8.6753, lat = 9.0820, zoom = 7)

```

***

To estimate spatial patterns of electricity access across Nigeria, satellite-derived nighttime light intensity data (VIIRS, 500m resolution, 2022–2024) were normalized, transformed and analysed using unsupervised clustering techniques to improve comparability across geographic areas. Several transformation techniques were tested, including logarithmic scaling, square root, Box-Cox, and histogram equalization, to optomise the distribution of light values. Ultimately, the normalized mean raster was selected for clustering, as it exhibited a near-symmetric, bell-shaped distribution ideal for unsupervised classification.

Two clustering algorithms were evaluated: K-Means and Gaussian Mixture Modeling (GMM). Both methods produced broadly consistent results, with over 80% spatial overlap in cluster assignments. However, GMM was selected for the final classification due to its probabilistic structure, which better captures gradual transitions and ambiguity, particularly in peri-urban or semi-electrified areas where light intensity changes are not abrupt.

Unlike K-Means, which imposes hard boundaries between clusters, GMM models overlapping distributions and is therefore more flexible in representing mixed or transitional access zones. Silhouette analysis supported a four-cluster solution, offering the best trade-off between statistical cohesion and interpretability.

The final classification assigned each 500m pixel to one of four electricity access tiers based on the distribution of normalized light intensity values:

- No/Very Low Access: ≤ 0.612

- Low Access: 0.612 – 0.730

- Medium Access: 0.730 – 0.890

- High Access: > 0.890

This GMM-based typology provides a spatially continuous, high-resolution map of electricity access across Nigeria. It enables a more targeted planning and identification of under-served populations, including hidden deprivation within partially electrified regions.


### **Energy Access Typologies** <br> Cluster-Specific Spatial Patterns

```{r access-panels, echo=FALSE}

library(leaflet)
library(raster)
library(htmltools)

# Color palette 
colors <- c("#6A51A3", "#2B8CBE", "#31A354", "#FED976")
labels <- c("Very Low/No Access", "Low Access", "Medium Access", "High Access")


# Cluster level raster
level_rasters <- lapply(1:4, function(i) {
  r <- raster_r
  r[r != i] <- NA
  r
})

# HTML containers
map_tags <- lapply(1:4, function(i) {
  pal <- colorNumeric(palette = colors[i], domain = i, na.color = "transparent")
  
  map <- leaflet() %>%
    addProviderTiles(providers$CartoDB.DarkMatter) %>%
    addRasterImage(level_rasters[[i]], colors = pal, opacity = 0.8, project = FALSE) %>%
    addLegend("bottomright", colors = colors[i], labels = labels[i], title = labels[i], opacity = 1) %>%
    setView(lng = 8.6753, lat = 9.0820, zoom = 6)
  
  # Use flexible layout
  tags$div(
    style = "flex: 1 1 48%; height: 45vh; margin: 1%;",
    map
  )
  })

# Wrap maps
browsable(
  tags$div(
    style = "display: flex; flex-wrap: wrap; justify-content: space-between; min-height: 900px; width: 100%;",
    map_tags
  )
)
```

***

The four maps depict distinct typologies of energy access derived from the GMM classification. Each typology corresponds to a different access tier and reveals the spatial distribution of energy inequality across Nigeria:

  - Dark purple areas indicate regions with **no or minimal** electricity access. These zones are predominantly located across the northern belt and represent the most energy-deprived parts of the country.
  
  - Blue areas represent zones with **limited but existing access**, often forming transitional buffers between poorly electrified regions and areas with moderate access. These tend to cluster around rural-urban interfaces or semi-electrified zones.
  
  - Green areas correspond to **moderate** electricity access, typically forming a halo around major cities and dense settlements. They are most prominent in the middle belt and northern fringes of southern Nigeria.
  
  - Yellow areas denote **high** electricity access, concentrated around major urban hubs such as Lagos, Abuja, and Port Hartcourt, as well as in the oil-producing Niger Delta. These areas also appear around isolated city centers in the north, highlighting localized electrification.

Together, the maps provide a nuanced spatial typology of electricity access, enabling visual identification of priority regions for energy investment and solar deployment.


### **Population Density and Energy Access** Identifying Underserved High-Density Areas

```{r, population-density, echo=FALSE, message=FALSE, warning=FALSE, results='asis'}

# -----------------------------
# 1. Load Population Density Raster
# -----------------------------
pop1_density <- rast("/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/CO REQUESTS/2024/Energy/Access_Solar_Analysis/graphics_presentation/pop1_density.tif")
pop2_density <- rast("/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/CO REQUESTS/2024/Energy/Access_Solar_Analysis/graphics_presentation/pop2_density.tif")
pop3_density <- rast("/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/CO REQUESTS/2024/Energy/Access_Solar_Analysis/graphics_presentation/pop3_density.tif")
pop4_density <- rast("/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/CO REQUESTS/2024/Energy/Access_Solar_Analysis/graphics_presentation/pop4_density.tif")

# -----------------------------
# 2. Convert Rasters
# -----------------------------
rasters <- list(raster(pop1_density), raster(pop2_density),
                raster(pop3_density), raster(pop4_density))

titles <- c("No/Very Low Access Areas", "Low Access Areas", "Medium Access Areas", "High Access Areas")

# -----------------------------
# 3. Define density breaks and color ramps
# -----------------------------
smooth_breaks <- c(0, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000)  # Reintroduce 0–100

access_palettes <- list(
  colorRampPalette(c("#F6EFF7", "#440154")),   # purple
  colorRampPalette(c("#E0ECF4", "#31688E")),   # blue
  colorRampPalette(c("#E5F5E0", "#35B779")),   # green
  colorRampPalette(c("#FFFACD", "#FDE725"))    # yellow
)
# -----------------------------
# 4. Generate Maps
# -----------------------------
map_tags <- lapply(1:4, function(i) {
  colors_raw <- access_palettes[[i]](length(smooth_breaks) - 1)
  colors_raw[1] <- "#D9D9D9"  # Set the 0–100 bin color

  pal <- colorBin(
    palette = colors_raw,
    bins = smooth_breaks,
    na.color = "transparent"
  )

  map <- leaflet() %>%
    addProviderTiles(providers$CartoDB.DarkMatter) %>%
    addRasterImage(rasters[[i]], colors = pal, opacity = 0.9, project = FALSE) %>%
    addLegend(
      position = "bottomright",
      pal = pal,
      values = values(rasters[[i]]),
      title = paste(titles[i], "\n(Population Density)"),
      opacity = 1
    ) %>%
    setView(lng = 8.6753, lat = 9.0820, zoom = 6)

  tags$div(
    style = "flex: 1 1 48%; height: 45vh; min-height: 400px; margin: 1%; box-sizing: border-box;",
    map
  )
})

# -----------------------------
# 5. Render all in flex layout
# -----------------------------
browsable(
  tags$div(
    style = "display: flex; flex-wrap: wrap; justify-content: space-between; align-items: stretch; width: 100%; min-height: 100vh;",
    map_tags
  )
)


```

***

To pinpoint where energy deprivation intersects most critically with human settlement, the analysis overlays the GMM classified electricity access typologies with smoothed population density surfaces derived from the Global Human Settlement Layer (GHS-POP). GHS-POP provides gridded population estimates at ~1km resolution, enabling disaggregated spatial analysis across the four electricity access tiers.

To emphasize regional clusters over isolated outliers, a 51×51 pixel kernel smoothing filter was applied to the population rasters within each access category. This revealed not only where people live, but how densely they are concentrated. Pixels with fewer than 100 people/km² were rendered in gray to de-emphasize sparsely populated zones and instead highlight areas with concentrated human presence.

The resulting maps reveal a stark spatial mismatch in many parts of the country: large, densely populated areas, particularly across northern Nigeria and the Middle Belt, fall within zones classified as having very low or no electricity access. These hotspots represent high-priority intervention zones, where infrastructure deficits directly affect large populations.

Conversely, high-access zones align closely with major urban centers particularly in the southern regions of the country, confirming an urban–infrastructure nexus. Medium access areas form a transitional ring around secondary cities and expanding peri-urban zones, while low access areas show scattered yet significant population densities, often in emerging rural towns or underserved settlements.

Some areas within the “very low access” class appear sparsely populated. This is expected in locations such as national parks, wetlands, or terrain unsuitable for habitation, and may also reflect limitations of satellite-based population detection in dispersed rural areas.

By intersecting electricity access classifications with population density, the analysis shifts from infrastructure mapping to human-centered energy diagnostics, providing a sharper basis for prioritizing interventions based on real-world needs.


### **State-Level Energy Poverty Estimates** <br> Disaggregating Electricity Access by Population and Geography


```{r energy-poverty-state, echo=FALSE, message=FALSE, warning=FALSE}

# Aggregates of energy poverty by access level

  population_by_access <- read.csv("/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/CO REQUESTS/2024/Energy/Access_Solar_Analysis/graphics_presentation/population_by_access.csv")
  population_by_access$Labels2 <- factor(population_by_access$Labels, levels = c("High Access", "Medium Access", "Low Access", "No/Very Low Access"))  
  population_by_access <- population_by_access[order(population_by_access$Labels2),]

  fig <- plot_ly(population_by_access,
                 x = ~Labels2, 
                 y = ~Percentage, 
                 type = 'bar',
                 text = ~label_text,
                 textposition = 'auto',
                 marker = list(color = rev(c("#440154FF", "#31688EFF", "#35B779FF", "#FDE725FF")))
  )
  
  fig_pop_access <- fig %>% layout(
    title = "Est. Population by Access Level",
    xaxis = list(title = "", showgrid = FALSE),
    yaxis = list(title = "", showgrid = FALSE, showticklabels = FALSE),
    uniformtext = list(minsize = 10, mode = 'show')
  )

# ---------------------------------------
# State level percentage calculations
# ---------------------------------------

# Data prep
  pop_raw <- "/Users/chinpihoikipgen/Downloads/temp_files/GHS_POP_2025.tif"
  raster_analyse <- "/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/CO REQUESTS/2024/Energy/Access_Solar_Analysis/graphics_presentation/gmm_access.tif"

  population <- rast(pop_raw)
  raster_analyse <- rast(raster_analyse)
  
  # Nigeria boundaries

  nigeria_shape <- st_read(
    "/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/GRAPHICS/SHAPEFILES/NIGERIA_SHAPEFILE/nga_admbnda_adm0_osgof_20190417.shp",
    quiet = TRUE)
  
  nigeria_shape <- st_make_valid(nigeria_shape)  # Need to fix geometry issues
  nigeria_vect <- (vect(nigeria_shape)) # For terra package
  
  # Reproject and Resample 
    
  if (crs(population) != crs(raster_analyse)) {
    population <- project(population, crs(raster_analyse))
  }
  
  if (!all(res(population) == res(raster_analyse))) {
    access_highres <- resample(raster_analyse, population, method="near")
  }
  
  # Mask
  population <- mask(population, nigeria_vect)
  access_highres <- mask(access_highres, nigeria_vect)
  
  # Create population rasters for each access level
  pop_level1 <- population * (access_highres == 1)  # No/Very Low Access
  pop_level2 <- population * (access_highres == 2)  # Low Access
  pop_level3 <- population * (access_highres == 3)  # Medium Access
  pop_level4 <- population * (access_highres == 4)  # High Access
  
# MERGE WITH STATE SHAPEFILE  
  
  state_shapefile <- "/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/GRAPHICS/SHAPEFILES/NIGERIA_SHAPEFILE/nga_admbnda_adm1_osgof_20190417.shp"
  state_boundaries <- vect(state_shapefile)  
  
  # Match CRS
  if (crs(state_boundaries) != crs(population)) {
    state_boundaries <- project(state_boundaries, crs(population))
  }
  
  # Check
  #same.crs(state_boundaries, population)
  
  # Extract zonal statistics
  state_raster <- rasterize(state_boundaries, population, field="ADM1_EN")  
  
  state_total <- zonal(population, state_raster, fun="sum", na.rm=TRUE)
  state_no_access <- zonal(pop_level1, state_raster, fun="sum", na.rm=TRUE)
  state_low_access <- zonal(pop_level2, state_raster, fun="sum", na.rm=TRUE)
  state_med_access <- zonal(pop_level3, state_raster, fun="sum", na.rm=TRUE)
  state_high_access <- zonal(pop_level4, state_raster, fun="sum", na.rm=TRUE)
  
  # Join Results
  state_results <- merge(state_total, state_no_access, by="ADM1_EN")
  names(state_results) <- c("ADM1_EN", "total_pop", "no_access_pop")
  
  state_results <- merge(state_results, state_low_access, by="ADM1_EN")
  names(state_results)[4] <- "low_access_pop"
  
  state_results <- merge(state_results, state_med_access, by="ADM1_EN")
  names(state_results)[5] <- "med_access_pop"
  
  state_results <- merge(state_results, state_high_access, by="ADM1_EN")
  names(state_results)[6] <- "high_access_pop"
  
  # Replace NA with zero
  state_results$no_access_pop[is.na(state_results$no_access_pop)] <- 0
  state_results$low_access_pop[is.na(state_results$low_access_pop)] <- 0
  state_results$med_access_pop[is.na(state_results$med_access_pop)] <- 0
  state_results$high_access_pop[is.na(state_results$high_access_pop)] <- 0
  
  # Calculate percentages and energy poverty
  state_results$no_access_pct <- (state_results$no_access_pop / state_results$total_pop) * 100
  state_results$low_access_pct <- (state_results$low_access_pop / state_results$total_pop) * 100
  state_results$med_access_pct <- (state_results$med_access_pop / state_results$total_pop) * 100
  state_results$high_access_pct <- (state_results$high_access_pop / state_results$total_pop) * 100
  state_results$energy_poor_pop <- state_results$no_access_pop + state_results$low_access_pop
  state_results$energy_poor_pct <- (state_results$energy_poor_pop / state_results$total_pop) * 100
  
  # Handle any NaN values from division by zero
  state_results$no_access_pct[is.nan(state_results$no_access_pct)] <- 0
  state_results$low_access_pct[is.nan(state_results$low_access_pct)] <- 0
  state_results$med_access_pct[is.nan(state_results$med_access_pct)] <- 0
  state_results$high_access_pct[is.nan(state_results$high_access_pct)] <- 0
  state_results$energy_poor_pct[is.nan(state_results$energy_poor_pct)] <- 0
  
  # Sort by energy poverty percentage
  state_results <- state_results[order(-state_results$energy_poor_pct), ]
  #state_results$ADM1_EN[state_results$ADM1_EN == "Federal Capital Territory"] <- "FCT"

# ---------------------------------------
# State level graphics
# ---------------------------------------
 
  # Pivot to long format
  state_results_long <- state_results %>%
    select(ADM1_EN, no_access_pct, low_access_pct, med_access_pct, high_access_pct) %>%
    pivot_longer(
      cols = ends_with("_pct"),
      names_to = "AccessLevel",
      values_to = "Percentage"
    ) %>%
    mutate(
      # Clean Access Level names for plotting
        AccessLevel = case_when(
        AccessLevel == "no_access_pct" ~ "No/Very Low Access",
        AccessLevel == "low_access_pct" ~ "Low Access",
        AccessLevel == "med_access_pct" ~ "Medium Access",
        AccessLevel == "high_access_pct" ~ "High Access"
      ),
      ADM1_EN = factor(ADM1_EN, levels = sort(unique(state_results$ADM1_EN))),
      AccessLevel = factor(AccessLevel, levels = c("No/Very Low Access", "Low Access", "Medium Access", "High Access"))
    )
  
  state_results_long <- state_results_long[order(state_results_long$ADM1_EN, state_results_long$AccessLevel),]

  # Plot 
  fig <- plot_ly(
    data = state_results_long,
    x = ~Percentage,
    y = ~ADM1_EN,
    color = ~AccessLevel,
    type = 'bar',
    orientation = 'h',
    text = ~paste0(ADM1_EN, "(", AccessLevel,"): ",round(Percentage), "%"),
    textposition = 'auto',
    hoverinfo = 'text',
    opacity = 0.70,  # adjust this value (e.g., 0.5 to 0.8)
    colors = c(
      "No/Very Low Access" = "#440154FF",  # deep purple
      "Low Access" = "#31688EFF",         # blue
      "Medium Access" = "#35B779FF",      # green
      "High Access" = "#FDE725FF"         # yellow
    )
  )
  
  
  # Customize layout
  fig_access_by_state <- fig %>% layout(
    barmode = 'stack',
    title = "Energy Access Levels by State (% population)",
    xaxis = list(title = "", ticksuffix = "%", showgrid = FALSE),
    yaxis = list(title = "", categoryorder = "array", showgrid = FALSE),
    legend = list(orientation = "h", x = -0.01, y = -0.05),
    margin = list(l = 100)  # adjust left margin to fit state names
  )
  
  #knitr::include_graphics("~/Downloads/State_Access_Levels.png")
  
   
  # Map
  
  state_vect <- vect(state_shapefile)
  state_sf <- st_as_sf(state_vect)
  
  state_results$ADM1_EN <- as.character(state_results$ADM1_EN)
  state_sf$ADM1_EN <- as.character(state_sf$ADM1_EN)
  
  state_map_data <- left_join(state_sf, state_results, by = "ADM1_EN")

  #display.brewer.all(type = "seq")
  #energy_pct_colors <- colorRampPalette(c("#f7fcf0", "#e0f3db", "#ccebc5", "#a8ddb5","#7bccc4", "#4eb3d3", "#2b8cbe", "#08589e"))(8)
  
  #energy_pct_colors <- colorRampPalette(c("#F2CB05", "#F2DA5E", "#F2E291", "#F2E8B3", "#F2EBC9"))(8)
  
  energy_pct_colors <- colorRampPalette(c(
  "#FFF7BC",  # light yellow
  "#FEC44F",  # golden
  "#FE9929",  # orange
  "#EC7014",  # dark orange
  "#CC4C02",  # burnt orange
  "#993404"   # deep brown-orange
))(8)
  
    
  #energy_pct_colors <- colorRampPalette(c("#5C4A72","#4B729C", "#61A57D", "#F5E676"))(8)
  pal <- colorNumeric(
  palette = (energy_pct_colors),
  domain = state_map_data$energy_poor_pct,
  na.color = "transparent"
)

  leaflet_map <- leaflet(state_map_data) %>%
  addProviderTiles(providers$CartoDB.DarkMatter) %>%
  addPolygons(
    fillColor = ~pal(energy_poor_pct),
    weight = 1,
    opacity = 1,
    color = "white",
    dashArray = "3",
    fillOpacity = 0.7,
    highlight = highlightOptions(
      weight = 2,
      color = "#666",
      fillOpacity = 0.9,
      bringToFront = TRUE
    ),
    label = ~paste0(ADM1_EN, ": ", round(energy_poor_pct, 1), "%"),
    labelOptions = labelOptions(
      style = list("font-weight" = "normal", padding = "3px 8px"),
      textsize = "13px",
      direction = "auto"
    )
  ) %>%
    setView(lng = 8.6753, lat = 9.0820, zoom = 5.5) %>%  # Adjust zoom as needed
    
    #fitBounds(bb["xmin"], bb["ymin"], bb["xmax"], bb["ymax"]) %>%

    addLegend(
    pal = pal,
    values = ~energy_poor_pct,
    opacity = 0.7,
    title = "Est. Energy Poverty (%)",
    position = "bottomright"
) %>% 
    addControl(
    html = HTML("<div style='font-size:10px; color:gray; padding:4px;'>*Note: Energy poverty defined as % population with no/very low or low access areas.</div>"),
    position = "topright"
  )
# ---------------------------------------
# Priority states
# ---------------------------------------
  # temp gradient - need to revisit colors
  
  energy_pct_colors <- colorRampPalette(c(
  "#FFF7BC", 
  "#FEC44F",  
  "#FE9929",  
  "#EC7014",  
  "#CC4C02",  
  "#993404"   
))(100)  
  
  fig_priority_states <- plot_ly(
  data = state_results,
  x = ~energy_poor_pct,
  y = ~energy_poor_pop,
  type = 'scatter',
  mode = 'markers+text',
  textposition = 'top center',
  hoverinfo = 'text',
  hovertext = ~paste0(
    "<b>", ADM1_EN, "</b><br>",
    "Energy Poor: ", round(energy_poor_pct, 1), "%<br>",
    "Pop. Energy Poor: ", format(round(energy_poor_pop), big.mark = ","), "<br>",
    "Total Pop: ", format(round(total_pop), big.mark = ",")
  ),
  marker = list(
    size = ~sqrt(total_pop) / 200,
    sizemode = 'diameter',
    sizeref = 2.0 * max(sqrt(state_results$total_pop)) / (100^2),
    color = ~energy_poor_pct,
    colorscale = list(
        list(0, "#FFF7BC"),
        list(0.2, "#FEC44F"),
        list(0.4, "#FE9929"),
        list(0.6, "#EC7014"),
        list(0.8, "#CC4C02"),
        list(1, "#993404")
      ),
    showscale = TRUE,
    colorbar = list(title = "% Energy Poor")
  ),
  text = ~ADM1_EN  # Labels for chart
)

fig_priority_states <- fig_priority_states %>% layout(
  title = "",
  xaxis = list(
    title = "% Population in Energy Poverty",
    ticksuffix = "%",
    gridcolor = "lightgray"
  ),
  yaxis = list(
    title = "Total Population in Energy Poverty",
    tickformat = ",",
    gridcolor = "lightgray"
  ),
  hovermode = "closest",
  showlegend = FALSE
)


    # HTML tags arragement
browsable(
  tagList(
    div(
      style = "height: 100%; width: 100%;",
      div(
        style = "display: flex; flex-direction: row; gap: 20px; height: 100%; width: 100%;",
        
        # Left
        div(
          style = "width: 50%; display: flex; flex-direction: column; height: 100%;",
          div(style = "flex: 0.4; overflow: auto; margin-bottom: 10px;", fig_pop_access),
          div(style = "flex: 1.6; overflow: auto;", fig_access_by_state)
        ),
        
        # Right
        div(
          style = "width: 50%; display: flex; flex-direction: column; gap: 20px;",
          div(style = "flex: 1;", leaflet_map),
          div(style = "flex: 1;", fig_priority_states)
        )
      )
    )
  )
)

  
```

***

This section disaggregates electricity access and energy poverty at the state level, combining GMM-classified nightlight-based access typologies with high-resolution population estimates (GHS-POP 2025) to reveal the scale and spatial distribution of under-served populations across Nigeria. While these are population estimates derived from the GHS-POP model, they still offer valuable spatial insight into settlement patterns and the population distribution of energy poverty.

By overlaying each electricity access class, ranging from No/Very Low to High Access, with gridded population surfaces (~1 km resolution), the analysis generates population-adjusted estimates of energy deprivation. This allows not only quantification of affected populations, but also identification of where energy poverty is most concentrated within each state.

To visualize these dynamics, the card presents three linked views:

- A national bar chart (top left) estimating population by access level, showing overall distribution;

- A state-level stacked bar chart (bottom left) showing the percentage of each state’s population in each access tier;

- An interactive map (right) depicting the share of population in energy poverty—defined as those residing in No/Very Low or Low Access zones.
- A bubble chart (bottom right) plotting each state by percentage of population in living in No/Very Low and Low energy access areas (X axis) against estimated total energy poor population (Y axis) and the size of the bubble reflecting total population at the state level. 

Together, these views highlight both relative and absolute disparities. They help identify priority states with both high energy poverty rates and large affected populations For instance, two states may have similar percentages of energy-poor populations, but vastly different population sizes—amplifying the need for population-adjusted targeting in energy access planning.


### **LGA-Level Energy Poverty Estimates** <br> Hotspots and Localised Deficit Scores

```{r energy-poverty-LGA-level, echo=FALSE, warnings = FALSE}

# ---------------------------------------
# LGA level percentages
# ---------------------------------------
   # Load LGA shapefile
  lga_shapefile <- "/Users/chinpihoikipgen/Documents/Documents – chinpihoi’s MacBook Pro - 1/NIGERIA/GRAPHICS/SHAPEFILES/NIGERIA_SHAPEFILE/nga_admbnda_adm2_osgof_20190417.shp"
  lga_boundaries <- vect(lga_shapefile)  
  
  # Match CRS
  if (crs(lga_boundaries) != crs(population)) {
    lga_boundaries <- project(lga_boundaries, crs(population))
  }
  
  # Check
  #same.crs(lga_boundaries, population)
  
  # Extract zonal statistics
  lga_raster <- rasterize(lga_boundaries, population, field="ADM2_PCODE")  
  
  zonal_total <- zonal(population, lga_raster, fun="sum", na.rm=TRUE)
  zonal_no_access <- zonal(pop_level1, lga_raster, fun="sum", na.rm=TRUE)
  zonal_low_access <- zonal(pop_level2, lga_raster, fun="sum", na.rm=TRUE)
  zonal_med_access <- zonal(pop_level3, lga_raster, fun="sum", na.rm=TRUE)
  zonal_high_access <- zonal(pop_level4, lga_raster, fun="sum", na.rm=TRUE)
  
  # Create a dataframe from zonal values to LGA names for lookup later
  lga_lookup <- data.frame(
    ADM2_PCODE = lga_boundaries$ADM2_PCODE,  
    LGA_Name = lga_boundaries$ADM2_EN,
    State = lga_boundaries$ADM1_EN
  )
  
  # Join 
  zonal_results <- merge(zonal_total, zonal_no_access, by="ADM2_PCODE")
  names(zonal_results) <- c("ADM2_PCODE", "total_pop", "no_access_pop")
  
  zonal_results <- merge(zonal_results, zonal_low_access, by="ADM2_PCODE")
  names(zonal_results)[4] <- "low_access_pop"
  
  zonal_results <- merge(zonal_results, zonal_med_access, by="ADM2_PCODE")
  names(zonal_results)[5] <- "med_access_pop"
  
  zonal_results <- merge(zonal_results, zonal_high_access, by="ADM2_PCODE")
  names(zonal_results)[6] <- "high_access_pop"
  
  # Replace NA with zero
  zonal_results$no_access_pop[is.na(zonal_results$no_access_pop)] <- 0
  zonal_results$low_access_pop[is.na(zonal_results$low_access_pop)] <- 0
  zonal_results$med_access_pop[is.na(zonal_results$med_access_pop)] <- 0
  zonal_results$high_access_pop[is.na(zonal_results$high_access_pop)] <- 0
  
  # Add LGA and state maps
  zonal_results <- merge(zonal_results, lga_lookup, by="ADM2_PCODE")
  
  # Calculate percentages and energy poverty
  zonal_results$no_access_pct <- (zonal_results$no_access_pop / zonal_results$total_pop) * 100
  zonal_results$low_access_pct <- (zonal_results$low_access_pop / zonal_results$total_pop) * 100
  zonal_results$med_access_pct <- (zonal_results$med_access_pop / zonal_results$total_pop) * 100
  zonal_results$high_access_pct <- (zonal_results$high_access_pop / zonal_results$total_pop) * 100
  zonal_results$energy_poor_pop <- zonal_results$no_access_pop + zonal_results$low_access_pop
  zonal_results$energy_poor_pct <- (zonal_results$energy_poor_pop / zonal_results$total_pop) * 100
  
  
  # NaN values handling
  zonal_results$no_access_pct[is.nan(zonal_results$no_access_pct)] <- 0
  zonal_results$low_access_pct[is.nan(zonal_results$low_access_pct)] <- 0
  zonal_results$med_access_pct[is.nan(zonal_results$med_access_pct)] <- 0
  zonal_results$high_access_pct[is.nan(zonal_results$high_access_pct)] <- 0
  zonal_results$energy_poor_pct[is.nan(zonal_results$energy_poor_pct)] <- 0
  
  
  # Sort by energy poverty percentage
  zonal_results <- zonal_results[order(-zonal_results$energy_poor_pct), ]
  
  # Deficit score - normalised
  zonal_results <- zonal_results %>%
  mutate(
    norm_pct = scales::rescale(energy_poor_pct),        # 0–1 scale
    norm_pop = scales::rescale(energy_poor_pop),        # 0–1 scale
    composite_score = round(0.5 * norm_pct + 0.5 * norm_pop,2)  # or weighted
  )
  
  # Merge with lga boundaries data
  lga_boundaries_merged <- merge(lga_boundaries, zonal_results, by="ADM2_PCODE", all.x=TRUE)
  
  # Replace NA with zero for energy-related fields
  lga_boundaries_merged$no_access_pop[is.na(lga_boundaries_merged$no_access_pop)] <- 0
  lga_boundaries_merged$low_access_pop[is.na(lga_boundaries_merged$low_access_pop)] <- 0
  lga_boundaries_merged$med_access_pop[is.na(lga_boundaries_merged$med_access_pop)] <- 0
  lga_boundaries_merged$high_access_pop[is.na(lga_boundaries_merged$high_access_pop)] <- 0
  lga_boundaries_merged$energy_poor_pop[is.na(lga_boundaries_merged$energy_poor_pop)] <- 0
  lga_boundaries_merged$energy_poor_pct[is.na(lga_boundaries_merged$energy_poor_pct)] <- 0
  
  
# ---------------------------------------
# LGA level maps
# ---------------------------------------
  pop_breaks <- pretty(lga_boundaries_merged$composite_score, n = 8)  
  
  # Create color function (colorBin for breaks, or colorQuantile for quantiles)
  pop_pal <- colorBin(
    palette = c("#f1eef6", "#d7b5d8", "#df65b0", "#dd1c77", "#980043"),
    domain = lga_boundaries_merged$composite_score,
    bins = pop_breaks,
    na.color = "transparent"
  )

  
  leaflet_lga <- leaflet(lga_boundaries_merged) %>%
  addProviderTiles(providers$CartoDB.DarkMatter) %>%
  addPolygons(
    fillColor = ~pop_pal(composite_score),
    weight = 0.5,
    color = "#ffffff",
    fillOpacity = 0.8,
    label = ~paste0(LGA_Name, " (", State, "): ", round(energy_poor_pct, 1), "% energy poor; ", "Energy Access Deficit Score: ",composite_score ),
    labelOptions = labelOptions(
      style = list("font-weight" = "normal", padding = "3px 8px"),
      textsize = "12px",
      direction = "auto"
    ),
    highlightOptions = highlightOptions(
      weight = 2,
      color = "#666",
      fillOpacity = 0.9,
      bringToFront = TRUE
    )
  ) %>%
    
    setView(lng = 8.6753, lat = 9.0820, zoom = 6) %>%  # zoom
  
  addLegend(
    pal = pop_pal,
    values = ~composite_score,
    title = "Energy Access Deficit Score",
    position = "bottomright",
    opacity = 0.7
  ) %>% 
    addControl(
    html = HTML("<div style='font-size:10px; color:gray; padding:4px;'>*Note: Energy poverty defined as % population with no/very low or low access areas.</div>"),
    position = "topright"
  )
  
   
# ---------------------------------------
# Top 50
# ---------------------------------------   

# Filter top 50 LGAs based on composite score
top_lgas <- zonal_results %>%
  arrange(desc(composite_score)) %>%
  slice(1:50) %>%
  mutate(label = paste0(LGA_Name, " (", State, ")"))  # For y-axis labels

# Plot
fig_top50 <- plot_ly(
  data = top_lgas,
  x = ~composite_score,
  y = ~reorder(label, composite_score),
  type = 'bar',
  orientation = 'h',
  marker = list(color = "#980043"),
  hoverinfo = 'text',
  text = ~paste0(
    "<b>", LGA_Name, " (", State, ")</b><br>",
    "Energy Poor (%): ", round(energy_poor_pct, 1), "%<br>",
    "Population Energy Poor: ", format(round(energy_poor_pop), big.mark = ","), "<br>",
    "Score: ", composite_score
  )
) %>% layout(
  title = "Top 50 LGAs by Energy Access Deficit Score",
  xaxis = list(title = "Deficit Score"),
  yaxis = list(title = "", automargin = TRUE),
  margin = list(l = 150)
)
  
# ---------------------------------------
# LGA level table
# ---------------------------------------
  zonal_results_table <- zonal_results %>% 
  select(LGA_Name, State, no_access_pct, low_access_pct, med_access_pct, high_access_pct, energy_poor_pct, composite_score) %>% 
    mutate(across(ends_with("pct"), ~round(.x, 2))) %>%
  rename(
    `No Access (%)` = no_access_pct,
    `Low Access (%)` = low_access_pct,
    `Medium Access (%)` = med_access_pct,
    `High Access (%)` = high_access_pct,
    `Energy Poor (%)` = energy_poor_pct,
    `Composite Score` = composite_score
  )
  
  table_lga <-  DT::datatable(
  zonal_results_table,
  options = list(
    pageLength = 80,
    scrollX = TRUE,
    autoWidth = TRUE
  ),
  rownames = FALSE,
  filter = 'top',
  caption = htmltools::tags$caption("LGA-Level Energy Access Summary")
) %>%
  formatStyle(
    'Composite Score',
    background = styleColorBar(zonal_results_table$`Composite Score`, '#dd1c77'),
    backgroundSize = '80% 70%',
    backgroundRepeat = 'no-repeat',
    backgroundPosition = 'center'
  )
  
    browsable(
  tagList(
    div(
      style = "display: flex; flex-direction: row; height: 100%; gap: 20px;",

      # Left column
      div(
        style = "flex: 1; height: 100%; overflow: auto;",
        table_lga  # or stacked charts div
      ),

      # Right 
      div(
        style = "flex: 1; height: 100%;",
        leaflet_lga
      )
    )
  )
)

```

***

The analysis was extended to cater for a more operational and locally actionable scale, energy access estimates were disaggregated to Nigeria’s 774 LGAs. This LGA-level view allows for finer geographic targeting and supports more tailored interventions, especially in high-burden and under-served communities that may be overlooked in state-level averages.

To synthesize two dimensions of energy poverty intensity (% of population without access) and scale (absolute number affected), a composite **Energy Access Deficit** score was developed. This score combines normalized values of energy poverty percentage and estimated energy-poor population to flag LGAs where unmet energy needs are both widespread and numerically large. 

The interactive map displays LGA-level Energy Access Deficit scores across Nigeria, while the accompanying searchable table provides access statistics and scores by LGA and state.

**Note:** Population estimates are derived from modeled data (GHS-POP 2025) and should be interpreted as indicative. While not based on recent census data, they offer valuable insight into spatial patterns of deprivation and remain useful for planning and prioritization.


```{r, eval = FALSE}

browsable(
  tagList(
    div(
      style = "display: flex; flex-direction: row; gap: 20px; height: 100%;",

      # Left column: LGA table
      div(
        style = "width: 50%; height: 100%; overflow: auto;",
        table_lga
      ),

      # Right column: Map + Bar chart stacked
      div(
        style = "width: 50%; display: flex; flex-direction: column; gap: 20px;",
        
        # Map (top)
        div(
          style = "flex: 1; height: 50%;",
          leaflet_lga
        ),

        # Top 50 LGAs chart (bottom)
        div(
          style = "flex: 1; height: 50%; overflow: auto;",
          fig_top50
        )
      )
    )
  )
)



```

### **Energy Access in Health Facilities** Mapping Energy Deprivation Across Public Hospitals

```{r, energy-poverty-health, echo = FALSE, warnings = FALSE, eval=FALSE }

  hospital_data <- read.csv("/Users/chinpihoikipgen/Downloads/temp_files/GRID3_NGA_health_facilities_V2.csv")
    hospital_data <- hospital_data %>% 
      filter(ownership_type%in%c("Local Government","State Government", "Federal Government"))
    # Convert hospitals to a spatial object
    hospitals_sf <- vect(hospital_data, geom = c("longitude", "latitude"), crs = "EPSG:4326")
  
  # Reproject to match access raster's CRS
  hospitals_sf <- project(hospitals_sf, crs(raster_data))
  
  # Check
  #same.crs(hospitals_sf, raster_data)
  
  # Extract access level for each hospital
  extracted_values <- terra::extract(access_highres, hospitals_sf)
  
  # Check structure
  #str(extracted_values)
  #head(extracted_values)
  
  # Assign values to hospital
  hospitals_sf$access_level <- extracted_values[,2]
  hospitals_sf$access_category <- factor(hospitals_sf$raster_data,
                                         levels = 1:4,
                                         labels = c("No/Very Low Access", 
                                                    "Low Access", 
                                                    "Medium Access", 
                                                    "High Access"))
  # Check distribution
  #table(hospitals_sf$access_category)
  # Hospitals in each access level
  hospitals_level1 <- hospitals_sf[hospitals_sf$raster_data == 1,]  # No/Very Low Access
  hospitals_level2 <- hospitals_sf[hospitals_sf$raster_data == 2,]  # Low Access
  hospitals_level3 <- hospitals_sf[hospitals_sf$raster_data == 3,]  # Medium Access
  hospitals_level4 <- hospitals_sf[hospitals_sf$raster_data == 4,]  # High Access
  
  # Plot each access level with hospital overlay
  par(mfrow=c(2,2))
  
  # No/Very Low Access
  plot(access_level1_mask, main="No/Very Low Access Areas", 
       col=c("white", cluster_colors[1]), legend=FALSE)
  plot(hospitals_level1, col="red", pch=16, cex=0.2, add=TRUE)
  plot(nigeria_vect, add=TRUE, border="black", lwd=0.5)
  legend("bottomright", legend=paste0("Hospitals: ", nrow(hospitals_level1)), 
         cex=0.7, bty="n")
  
  # Low Access
  plot(access_level2_mask, main="Low Access Areas", 
       col=c("white", cluster_colors[2]), legend=FALSE)
  plot(hospitals_level2, col="red", pch=16, cex=0.2, add=TRUE)
  plot(nigeria_vect, add=TRUE, border="black", lwd=0.5)
  legend("bottomright", legend=paste0("Hospitals: ", nrow(hospitals_level2)), 
         cex=0.7, bty="n")
  
  # Medium Access
  plot(access_level3_mask, main="Medium Access Areas", 
       col=c("white", cluster_colors[3]), legend=FALSE)
  plot(hospitals_level3, col="red", pch=16, cex=0.2, add=TRUE)
  plot(nigeria_vect, add=TRUE, border="black", lwd=0.5)
  legend("bottomright", legend=paste0("Hospitals: ", nrow(hospitals_level3)), 
         cex=0.7, bty="n")
  
  # High Access
  plot(access_level4_mask, main="High Access Areas", 
       col=c("white", cluster_colors[4]), legend=FALSE)
  plot(hospitals_level4, col="red", pch=16, cex=0.2, add=TRUE)
  plot(nigeria_vect, add=TRUE, border="black", lwd=0.5)
  legend("bottomright", legend=paste0("Hospitals: ", nrow(hospitals_level4)), 
         cex=0.7, bty="n")
  



```

***

[graphics to be rendered]
This section overlays public hospital locations with GMM-classified electricity access typologies to highlight the availability of energy infrastructure at health facilities across Nigeria. By categorizing each hospital into four access levels—No/Very Low, Low, Medium, and High—the analysis identifies critical service points operating under severe energy constraints.

Public hospitals in No/Very Low Access zones often serve as primary health centers for underserved communities. Identifying and mapping these facilities provides a clear entry point for infrastructure investment planning—especially solarization or mini-grid solutions.

To support prioritization, the dashboard presents:

- A state-level bar chart showing the percentage of hospitals in No/Low Access areas

- An interactive map of hospital points, color-coded by access level

- Summary counts of hospitals per access level

**Note:** Only public hospitals were included (federal, state, and local government facilities).

**Critical Healthcare Infrastructure Findings:**

- **68% of public healthcare facilities** operate in areas with poor electricity access
- **892 hospitals and health centers** have very low/no electricity access
- **1,526 facilities** (68% of total) are classified as "energy poor"

**Priority States for Healthcare Energy Interventions:**
The northern states of Borno, Katsina, Bauchi, and Jigawa emerge as top priorities, combining high numbers of energy-poor healthcare facilities with large populations lacking electricity access.

This analysis underscores the critical intersection between energy poverty and healthcare delivery, where reliable electricity is essential for medical equipment, vaccine cold chains, lighting for night deliveries, and overall healthcare quality.


### **Energy Poverty and Solar Potential** <br> Strategic Opportunities for Renewable Energy

```{r, energy-solar, echo = FALSE}


```

***

To do